package Demo5;


import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class BinaryTree {
    static class TreeNode{
        private char val;
        private TreeNode left;
        private TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }

        public TreeNode root; // 根节点
    }


    /*
        A
       / \
      B   C
     / \ / \
    D  E F  G
        \
         H
*/

    //    创建 二叉树
    public TreeNode createTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;
        return A;
    }

//    求二叉树高度
    public int getHeight(TreeNode root){
        if (root == null){
            return 0;
        }

//        二叉树高度是左右子树的较大值加一( 根节点 )
        return Math.max(getHeight(root.left),getHeight(root.right)) + 1;
    }

    public List<Character> preOrderTraversal(TreeNode root) {
//        使用栈 完成 非递归的前序遍历
//        前序遍历: 根 左 右
        List<Character> ret = new ArrayList<>();

        if (root == null) {
            return ret;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            ret.add(node.val);
//            因为栈的特点是 后进先出 所以先放右子树
            if (node.right != null){
                stack.push(node.right);
            }
            if (node.left != null){
                stack.push(node.left);
            }
        }
        return ret;
    }

    // 非递归中序遍历
    public List<Character> inOrderTraversal(TreeNode root) {
        List<Character> result = new ArrayList<>();

        if (root == null) {
            return result;
        }

        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(!stack.isEmpty() || cur != null){
            if (cur != null){
                stack.push(cur);
                cur = cur.left;
            }else {
                cur = stack.pop();
                result.add(cur.val);
                cur = cur.right;
            }
        }
        return result;
    }

    // 非递归后序遍历（使用两个栈）
    public List<Character> postOrderTraversal(TreeNode root) {
        List<Character> ret = new ArrayList<>();

        if (root == null) {
            return ret;
        }

        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();

        stack1.push(root);
        while (!stack1.isEmpty()) {
            TreeNode node = stack1.pop();
            stack2.push(node);
            if (node.left != null) {
                stack1.push(node.left);
            }
            if (node.right != null) {
                stack1.push(node.right);
            }
        }
        while (!stack2.isEmpty()) {
            ret.add(stack2.pop().val);
        }
        return ret;
    }

    // 非递归后序遍历，使用一个栈
    public List<Character> postOrderTraversalOneStack(TreeNode root) {
        List<Character> result = new ArrayList<>();
        if (root == null) {
            return result;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode cur = stack.peek();
            if (cur.left != null && root != cur.left && root != cur.right){
//                有左树 且左树没处理过
                stack.push(cur.left);
            } else if (cur.right != null && root != cur.right) {
//                有右树 且右树没处理过
                stack.push(cur.right);
            }else {
//                左右数 都为空 或者 都处理过了
                result.add(cur.val);
                root = stack.pop();
            }
        }
        return result;
    }

    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        TreeNode root = binaryTree.createTree();

        int height = binaryTree.getHeight(root);
        System.out.println(height);
    }
}
